import { IStandardFileInfo, StandardFileInfo } from '@/ts/core/thing/fileinfo';
import { schema } from '@/ts/base';
import { TaskContentType } from '@/ts/base/model';
import { XAssignTask, XReportTree } from '@/ts/base/schema';
import { IDirectory, XCollection } from '@/ts/core';
import { AssignStatusType } from '@/ts/base/enum';
import { generateShortUuid } from '@/ts/base/common/uuid';

export interface IAssignTaskModel extends IStandardFileInfo<schema.XAssignTaskModel> {
  /** 关联任务 */
  assignTasks: schema.XAssignTask[];
  /** 应用 */
  directoryId: string;
  /** 办事 */
  workId: string;
  /** 报表树ID */
  treeId: string;
  /** 类型 */
  type: TaskContentType;

  /** 新建下发任务 */
  create(task: schema.XAssignTask): Promise<schema.XAssignTask | undefined>;

  /** 删除下发任务 */
  hardDeleteTask(task: schema.XAssignTask): Promise<void>;

  /** 加载下发任务 */
  loadTasks(): Promise<schema.XAssignTask[]>;

  /** 加载报表树 */
  loadReportTree(): Promise<schema.XReportTree | undefined>;
}

export class AssignTaskModel
  extends StandardFileInfo<schema.XAssignTaskModel>
  implements IAssignTaskModel
{
  constructor(_metadata: schema.XAssignTaskModel, directory: IDirectory) {
    super(_metadata, directory, directory.resource.assignTaskModelColl);
    this._metadata = _metadata;
    const resource = directory.resource;
    this.assignTaskColl = resource.assignTaskColl;
    this.assignTaskTreeColl = resource.assignTaskTreeColl;
    this.assignTaskPublicColl = resource.assignTaskPublicColl;
    this.reportTreeColl = directory.target.resource.reportTreeColl;
    this.reportTreeNodeColl = directory.target.resource.reportTreeNodeColl;
  }
  reportTreeColl: XCollection<schema.XReportTree>;
  reportTreeNodeColl: XCollection<schema.XReportTreeNode>;
  assignTaskColl: XCollection<schema.XAssignTask>;
  assignTaskPublicColl: XCollection<schema.XAssignTask>;
  assignTaskTreeColl: XCollection<schema.XAssignTaskTree>;
  assignTasks: schema.XAssignTask[] = [];
  get type() {
    return this._metadata.content.type;
  }

  get cacheFlag() {
    return 'assign-task-model';
  }

  get directoryId() {
    return this._metadata.content.directoryId;
  }

  get workId() {
    return this._metadata.content.workId;
  }

  get treeId() {
    return this._metadata.content.treeId;
  }

  async create(task: XAssignTask): Promise<XAssignTask | undefined> {
    if (task.belongId !== this.belongId) {
      throw new Error('任务树根节点与当前任务节点归属不一致');
    }
    let tasks = await this.assignTaskPublicColl.loadSpace({
      options: {
        match: {
          modelId: this.metadata.id,
          periodType: this.metadata.periodType,
          period: task.period,
        },
      },
    });
    if (tasks.length > 0) {
      throw new Error(`任务 ${task.period} 已存在`);
    }
    task.id = generateShortUuid();
    task.treeId = generateShortUuid();
    task.nodePath = task.id;
    this.metadata.content.treeId = task.treeId;
    this.metadata.content.sessionId = this.target.id;
    return await this.assignTaskPublicColl.insert({
      ...task,
      typeName: '任务',
      code: task.id,
      distContent: this.metadata.content ?? {},
      assignContent: this.metadata.content ?? {},
      modelId: this.id,
      periodType: this.metadata.periodType,
      receiveUserId: this.userId,
      taskStatus: AssignStatusType.RECEIVED,
      assignName: this.metadata.name,
    });
  }

  async loadTasks(): Promise<XAssignTask[]> {
    let tasks = await this.assignTaskPublicColl.loadSpace({
      options: {
        match: {
          modelId: this.id,
          periodType: this.metadata.periodType,
        },
        sort: {
          period: -1,
        },
      },
    });
    this.assignTasks = tasks;
    return tasks;
  }

  async checkTasks() {
    let xAssignTasks = await this.loadTasks();
    if (xAssignTasks.length > 0) {
      throw new Error('任务模板已关联任务，无法删除，请先删除所有关联任务');
    }
  }

  async hardDeleteTask(task: XAssignTask): Promise<void> {
    await this.assignTaskPublicColl.remove(task);
  }

  async copy(destination: IDirectory): Promise<boolean> {
    if (this.allowCopy(destination)) {
      return await super.copyTo(destination.id, destination.resource.assignTaskModelColl);
    }
    return false;
  }

  async move(destination: IDirectory): Promise<boolean> {
    if (this.allowMove(destination)) {
      return await super.moveTo(destination, destination.resource.assignTaskModelColl);
    }
    return false;
  }

  override async delete(notify?: boolean): Promise<boolean> {
    await this.checkTasks();
    return super.delete(notify);
  }

  override async hardDelete(notify?: boolean): Promise<boolean> {
    await this.checkTasks();
    return super.hardDelete(notify);
  }

  async loadReportTree(): Promise<XReportTree | undefined> {
    const reportTrees = await this.reportTreeColl.find([this.treeId]);
    if (reportTrees.length > 0) {
      return reportTrees[0];
    }
    return Promise.resolve(undefined);
  }
}
